/** @file    CoderXML_Core.cpp
 *  @author  Alessandro Polo
 *  @version $Id: CoderXML_Core.cpp 2248 2010-03-29 01:29:04Z alex $
 *  @brief
 * File containing methods for Serialization.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include <framework/database/CoderXML_Core.h>
 #include <framework/database/EncoderXML.h>


using namespace std;
namespace wosh {
 namespace database {

void EncoderXML_register_Core()
 {
	EncoderXML::registerDataType( "wosh::Communicator",				new EncoderXML_template__Communicator() );

	EncoderXML::registerDataType( _Variant_TYPE,					new EncoderXML_template__Variant() );
	EncoderXML::registerDataType( _NEW_List_TYPE,					new EncoderXML_template__NEW_List() );
	EncoderXML::registerDataType( _Permission_TYPE,					new EncoderXML_template__Permission() );
	EncoderXML::registerDataType( _URI_TYPE,						new EncoderXML_template__URI() );
	EncoderXML::registerDataType( _Property_TYPE,					new EncoderXML_template__Property() );
	EncoderXML::registerDataType( _PropertiesProvider_TYPE,			new EncoderXML_template__PropertiesProvider() );

	EncoderXML::registerDataType( wosh::TreeNode::className(),		new EncoderXML_template__TreeNode() );
	EncoderXML::registerDataType( wosh::Tree::className(),			new EncoderXML_template__Tree() );

	EncoderXML::registerDataType( wosh::ObjectTypeInfo::className(),new EncoderXML_template__ObjectTypeInfo() );

	EncoderXML::registerDataType( _Message_TYPE,					new EncoderXML_template__Message() );
	EncoderXML::registerDataType( _SecurityToken_TYPE,				new EncoderXML_template__SecurityToken() );
	EncoderXML::registerDataType( _MessageNetworkForwarding_TYPE,	new EncoderXML_template__MessageNetworkForwarding() );
	
	EncoderXML::registerDataType( _Request_TYPE,					new EncoderXML_template__Request() );
	EncoderXML::registerDataType( _Response_TYPE,					new EncoderXML_template__Response() );
	EncoderXML::registerDataType( _Fact_TYPE,						new EncoderXML_template__Fact() );
//	EncoderXML::registerDataType( "wosh::Notification",				new EncoderXML_template__Notification() );
	EncoderXML::registerDataType( _SystemError_TYPE,				new EncoderXML_template__SystemError() );


	EncoderXML::registerDataType( _Table_TYPE,						new EncoderXML_template__Table() );

	EncoderXML::registerDataType( _User_TYPE,						new EncoderXML_template__User() );

	EncoderXML::registerDataType( _WoshHost_TYPE,					new EncoderXML_template__WoshHost() );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Communicator::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Communicator* object = dynamic_cast<const Communicator*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	if ( compact ) {
		ret += EncoderXML_template__Object().serializeTo( object, doc, contNode, true );
	 }
	else {
		QDomElement objectNode = doc.createElement("object");
		contNode.appendChild(objectNode);
		ret += EncoderXML_template__Object().serializeTo( object, doc, objectNode, false );

	 }

	contNode.setAttribute("kernelhost", QString(object->getKernelHost().c_str()) );

	QDomElement cTypeNode = doc.createElement("channelTypes");
	cTypeNode.appendChild( doc.createTextNode( QString::number(object->getChannelTypes()) ) );
	contNode.appendChild(cTypeNode);

	QDomElement cLinkNode = doc.createElement("channelLink");
	cLinkNode.appendChild( doc.createTextNode( QString::number(object->getChannelLink()) ) );
	contNode.appendChild(cLinkNode);

	QDomElement cCostNode = doc.createElement("cost");
	cCostNode.appendChild( doc.createTextNode( QString::number(object->getCost()) ) );
	contNode.appendChild(cCostNode);

	QDomElement cPriorityNode = doc.createElement("priority");
	cPriorityNode.appendChild( doc.createTextNode( QString::number(object->getPriority()) ) );
	contNode.appendChild(cPriorityNode);

	QDomElement cReliabilityNode = doc.createElement("reliability");
	cReliabilityNode.appendChild( doc.createTextNode( QString::number(object->getReliability()) ) );
	contNode.appendChild(cReliabilityNode);


	(void)compact;
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Communicator::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Communicator* object = dynamic_cast<Communicator*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement objectNode = contNode.namedItem("object").toElement();
	if ( !objectNode.isNull() )
		ret += EncoderXML_template__Object().deserializeFrom( object, objectNode );
	else
		ret += EncoderXML_template__Object().deserializeFrom( object, contNode );


	QDomElement kernelhostNode = contNode.namedItem("kernelhost").toElement();
	if ( kernelhostNode.isNull() )
		object->setKernelHost( string( contNode.text().toLatin1().data() ) );
	else
		object->setKernelHost( string( kernelhostNode.text().toLatin1().data() ) );

	QDomElement contNode_cost = contNode.namedItem("cost").toElement();
	if ( contNode_cost.isNull() )
		object->setCost( contNode.attribute("cost").toDouble() );
	else
		object->setCost( contNode_cost.text().toDouble() );

	QDomElement contNode_priority = contNode.namedItem("priority").toElement();
	if ( contNode_priority.isNull() )
		object->setCost( contNode.attribute("priority").toInt() );
	else
		object->setCost( contNode_priority.text().toInt() );

	QDomElement contNode_reliability = contNode.namedItem("reliability").toElement();
	if ( contNode_reliability.isNull() )
		object->setCost( contNode.attribute("reliability").toLong() );
	else
		object->setCost( contNode_reliability.text().toLong() );

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Variant::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Variant* object = dynamic_cast<const Variant*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QString type = QString( object->getTypeAsString() );

	if ( compact ) {
		contNode.appendChild( doc.createTextNode( QString(object->toString().c_str()) ) );
		contNode.setAttribute("type", type );
	 }
	else {
		QDomElement dataNode = doc.createElement("data");
		dataNode.appendChild( doc.createTextNode( QString(object->toString().c_str()) ) );
		contNode.appendChild(dataNode);

		QDomElement typeNode = doc.createElement( "type" );
		typeNode.appendChild( doc.createTextNode( type ) );
		contNode.appendChild(typeNode);
	 }
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Variant::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Variant* object = dynamic_cast<Variant*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	object->clear();

	QString data;
	QDomElement dataNode = contNode.namedItem("data").toElement();
	if ( dataNode.isNull() )
		data = contNode.text();
	else
		data = dataNode.text();

	object->fromString( data.toLatin1().data() );
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__NEW_List::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const NEW_List* object = dynamic_cast<const NEW_List*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	if ( !compact )
		contNode.setAttribute("size", QString::number(object->size()) );

	NEW_List::ConstIterator it;
	const NEW_List::ConstIterator it_end = object->end();
	for (it=object->begin(); it!=it_end; ++it) {
		QDomElement itemNode = doc.createElement("item");
		const ISerializable* cItem = *it;
		if ( cItem != NULL ) {
			itemNode.setAttribute("classname", QString(cItem->getClassName()) );
			ret += EncoderXML::serializeTo(cItem, doc, itemNode, compact );
		}
		contNode.appendChild(itemNode);
	}

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__NEW_List::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	NEW_List* object = dynamic_cast<NEW_List*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	unsigned int size = 0;
	QDomElement sizeNode = contNode.namedItem("size").toElement();
	if ( sizeNode.isNull() )
		size = contNode.attribute("size").toInt();
	else
		size = sizeNode.text().toInt();
	object->reserve(size);

	QDomNodeList nodeList = contNode.childNodes();
	for( unsigned int col=0; col<nodeList.length(); ++col ) {
		QDomElement itemNode = nodeList.item(col).toElement();
		string item_type( itemNode.attribute("classname").toLatin1().data() );
		if ( item_type == "" )
			item_type = _Variant_TYPE;
		EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(item_type);
		if ( obj_ser != NULL ) {
			ISerializable* item_data = obj_ser->allocObject();
			ret += obj_ser->deserializeFrom(item_data, itemNode);
			object->push_back( item_data );
		 }
		else
			ret += WRET_ERR_PARAM;
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Table::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Table* object = dynamic_cast<const Table*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;
	unsigned int rows = object->getRows();
	unsigned int cols = object->getCols();

	contNode.setAttribute("name", QString(object->getTableName().c_str()) );
	contNode.setAttribute("rows", QString::number(rows) );
	contNode.setAttribute("cols", QString::number(cols) );

	if ( object->hasHeaderHorizontal() ) {
		QDomElement hHorizontalNode = doc.createElement("header-horizontal");
		for (unsigned int col=0; col<cols; col++) {
			QDomElement itemNode = doc.createElement("item");
			const ISerializable* cItem = object->getHeaderHorizontal(col);
			if ( cItem != NULL ) {
				itemNode.setAttribute("classname", QString(cItem->getClassName()) );
				EncoderXML::serializeTo(cItem, doc, itemNode, compact );
			}
			hHorizontalNode.appendChild(itemNode);
		}
		contNode.appendChild(hHorizontalNode);
	 }
	if ( object->hasHeaderVertical() ) {
		QDomElement hVerticalNode = doc.createElement("header-vertical");
		for (unsigned int row=0; row<rows; row++) {
			QDomElement itemNode = doc.createElement("item");
			const ISerializable* cItem = object->getHeaderVertical(row);
			if ( cItem != NULL ) {
				itemNode.setAttribute("classname", QString(cItem->getClassName()) );
				EncoderXML::serializeTo(cItem, doc, itemNode, compact );
			}
			hVerticalNode.appendChild(itemNode);
		}
		contNode.appendChild(hVerticalNode);
	 }

	QDomElement tblItems = doc.createElement("items");
	for (unsigned int row=0; row<rows; row++) {
		QDomElement cRow = doc.createElement("row");
		for (unsigned int col=0; col<cols; col++) {
			QDomElement itemNode = doc.createElement("item");
			const ISerializable* cItem = object->get(row, col);
			if ( cItem != NULL ) {
				itemNode.setAttribute("classname", QString(cItem->getClassName()) );
				EncoderXML::serializeTo(cItem, doc, itemNode, compact );
			}
			cRow.appendChild(itemNode);
		}
		tblItems.appendChild(cRow);
	}
	contNode.appendChild(tblItems);

	(void)compact;

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Table::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Table* object = dynamic_cast<Table*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement nameNode = contNode.namedItem("name").toElement();
	if ( nameNode.isNull() )
		object->setTableName( string( contNode.attribute("name").toLatin1().data() ) );
	else
		object->setTableName( string( nameNode.text().toLatin1().data() ) );

	unsigned int rows = 0;
	unsigned int cols = 0;
	QDomElement rowsNode = contNode.namedItem("rows").toElement();
	if ( rowsNode.isNull() )
		rows = contNode.attribute("rows").toInt();
	else
		rows = rowsNode.text().toInt();

	QDomElement colsNode = contNode.namedItem("cols").toElement();
	if ( colsNode.isNull() )
		cols = contNode.attribute("cols").toInt();
	else
		cols = colsNode.text().toInt();

	object->alloc(rows, cols);

	QDomElement hHorizontalNode = contNode.namedItem("header-horizontal").toElement();
	QDomNodeList hHorizontalList = hHorizontalNode.childNodes();
	if ( hHorizontalList.length() == cols ) {
		object->allocHeaderHorizontal(true);
		for( unsigned int col=0; col<hHorizontalList.length(); ++col ) {
			QDomElement itemNode = hHorizontalList.item(col).toElement();
			string item_type( itemNode.attribute("classname").toLatin1().data() );
			EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(item_type);
			if ( obj_ser != NULL ) {
				ISerializable* item_data = obj_ser->allocObject();
				ret += obj_ser->deserializeFrom(item_data, itemNode);
				ret += object->setHeaderHorizontal( item_data, col );
			 }
			else
				ret += WRET_ERR_PARAM;
		 }
	 }

	QDomElement hVerticalNode = contNode.namedItem("header-vertical").toElement();
	QDomNodeList hVerticalList = hVerticalNode.childNodes();
	if ( hHorizontalList.length() == rows ) {
		object->allocHeaderVertical(true);
		for( unsigned int row=0; row<hVerticalList.length(); ++row ) {
			QDomElement itemNode = hVerticalList.item(row).toElement();
			string item_type( itemNode.attribute("classname").toLatin1().data() );
			EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(item_type);
			if ( obj_ser != NULL ) {
				ISerializable* item_data = obj_ser->allocObject();
				ret += obj_ser->deserializeFrom(item_data, itemNode);
				ret += object->setHeaderVertical( item_data, row );
			 }
			else
				ret += WRET_ERR_PARAM;
		 }
	 }

	QDomElement itemsNode = contNode.namedItem("items").toElement();
	QDomNodeList itemsList = itemsNode.childNodes();
	for( unsigned int row=0; row<itemsList.length(); ++row ) {
		QDomElement rowNode = itemsList.item(row).toElement();
		QDomNodeList itemList = rowNode.childNodes();
		for( unsigned int col=0; col<itemList.length(); ++col ) {
			QDomElement itemNode = itemList.item(col).toElement();
			string item_type( itemNode.attribute("classname").toLatin1().data() );
			EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(item_type);
			if ( obj_ser != NULL ) {
				ISerializable* item_data = obj_ser->allocObject();
				ret += obj_ser->deserializeFrom(item_data, itemNode);
				ret += object->set( item_data, row, col );
			 }
			else
				ret += WRET_ERR_PARAM;
		 }
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__TreeNode::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const TreeNode* object = dynamic_cast<const TreeNode*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement itemNode = doc.createElement("item");
	const ISerializable* cItem = object->getContent();
	if ( cItem != NULL ) {
		itemNode.setAttribute("classname", QString(cItem->getClassName()) );
		EncoderXML::serializeTo(cItem, doc, itemNode, compact );
	}
	contNode.appendChild(itemNode);

	if ( object->getChildren().isEmpty() )
		return ret;

	QDomElement childrenNode = doc.createElement("children");
	TreeNode::ChildConstIterator it;
	const TreeNode::ChildConstIterator it_end = object->getChildren().end();
	for( it=object->getChildren().begin(); it!=it_end; ++it) {
		if ( *it == NULL ) continue;
		const TreeNode* cNode = dynamic_cast<const TreeNode*>(*it);
		QDomElement childNode = doc.createElement("node");
		ret += EncoderXML_template__TreeNode::serializeTo( cNode, doc, childNode, compact );
		childrenNode.appendChild(childNode);
 	 }
	contNode.appendChild(childrenNode);

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__TreeNode::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	TreeNode* object = dynamic_cast<TreeNode*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement itemNode = contNode.namedItem("item").toElement();
	string item_type( itemNode.attribute("classname").toLatin1().data() );
	EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(item_type);
	if ( obj_ser != NULL ) {
		ISerializable* item_data = obj_ser->allocObject();
		ret += obj_ser->deserializeFrom(item_data, itemNode);
		object->setContent( item_data );
	 }
	else
		ret += WRET_ERR_PARAM;

	QDomElement childrenNode = contNode.namedItem("children").toElement();
	QDomNodeList childList = childrenNode.childNodes();
	for( unsigned int row=0; row<childList.length(); ++row ) {
		QDomElement childNode = childList.item(row).toElement();
		TreeNode* tNode = new TreeNode(object);
		ret += EncoderXML_template__TreeNode().deserializeFrom( tNode, childNode );
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Tree::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Tree* object = dynamic_cast<const Tree*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	if ( compact ) {
		contNode.setAttribute("name", QString(object->getTreeName().c_str()) );
		if ( object->hasRoot() )
			ret = EncoderXML_template__TreeNode().serializeTo( object->getRoot(), doc, contNode, compact );
	 }
	else {
		QDomElement nameNode= doc.createElement("name");
		nameNode.appendChild( doc.createTextNode( QString(object->getTreeName().c_str()) ) );
		contNode.appendChild(nameNode);
		if ( !object->hasRoot() )
			return WRET_OK;
		QDomElement rootNode= doc.createElement("root");
		ret = EncoderXML_template__TreeNode().serializeTo( object->getRoot(), doc, rootNode, compact );
		contNode.appendChild(rootNode);
	 }
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Tree::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Tree* object = dynamic_cast<Tree*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement contNode_name = contNode.namedItem("name").toElement();
	if ( contNode_name.isNull() )
		object->setTreeName( string( contNode.attribute("name").toLatin1().data() ) );
	else
		object->setTreeName( string( contNode_name.text().toLatin1().data() ) );

	TreeNode* rootNode = new TreeNode(NULL);
	QDomElement contNode_root = contNode.namedItem("root").toElement();
	if ( contNode_root.isNull() )
		ret = EncoderXML_template__TreeNode().deserializeFrom( rootNode, contNode );
	else {
		ret = EncoderXML_template__TreeNode().deserializeFrom( rootNode, contNode_root );
	 }
	object->setRoot(rootNode);
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Permission::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Permission* object = dynamic_cast<const Permission*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QString mask = QString(object->getMask().c_str());
	//QString("%1%2%3").arg(object->mask[0]).arg(object->mask[1]).arg(object->mask[2]);

	if ( compact ) {
		contNode.setAttribute("owner", QString(object->getOwner().c_str()) );
		contNode.setAttribute("group", QString(object->getGroup().c_str()) );
		contNode.setAttribute("mask", mask );
	 }
	else {
		QDomElement Node_owner = doc.createElement("owner");
		Node_owner.appendChild( doc.createTextNode( QString(object->getOwner().c_str()) ) );
		contNode.appendChild(Node_owner);

		QDomElement Node_group = doc.createElement("group");
		Node_group.appendChild( doc.createTextNode( QString(object->getGroup().c_str()) ) );
		contNode.appendChild(Node_group);

		QDomElement Node_mask = doc.createElement("mask");
		Node_mask.appendChild( doc.createTextNode( mask ) );
		contNode.appendChild(Node_mask);
	 }
	
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Permission::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Permission* object = dynamic_cast<Permission*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement contNode_owner = contNode.namedItem("owner").toElement();
	if ( contNode_owner.isNull() )
		object->setOwner( string( contNode.attribute("owner").toLatin1().data() ) );
	else
		object->setOwner( string( contNode_owner.text().toLatin1().data() ) );

	QDomElement contNode_group = contNode.namedItem("group").toElement();
	if ( contNode_group.isNull() )
		object->setGroup( string( contNode.attribute("group").toLatin1().data() ) );
	else
		object->setGroup( string( contNode_group.text().toLatin1().data())  );

	QDomElement contNode_mask = contNode.namedItem("mask").toElement();
	if ( contNode_mask.isNull() )
		object->setMask( string( contNode.attribute("mask").toLatin1().data() ) );
	else
		object->setMask( string( contNode_mask.text().toLatin1().data() ) );

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__URI::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const URI* object = dynamic_cast<const URI*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	contNode.appendChild(doc.createTextNode( QString(object->toString().c_str()) ));
	
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__URI::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	URI* object = dynamic_cast<URI*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	object->fromString( contNode.text().toLatin1().data() );

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Property::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Property* object = dynamic_cast<const Property*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( compact ) {
		contNode.setAttribute("key", QString(object->getKey().c_str()) );
		contNode.setAttribute("type", QString(object->getValue().getTypeAsString()) );
		contNode.setAttribute("value", QString(object->getValue().toString().c_str()) );
		contNode.setAttribute("permission", QString(object->getPermission().toString().c_str()) );
	 }
	else {
		QDomElement Node_key = doc.createElement("key");
		Node_key.appendChild( doc.createTextNode( QString(object->getKey().c_str()) ) );
		contNode.appendChild(Node_key);

		QDomElement Node_value = doc.createElement("value");
		EncoderXML_template__Variant().serializeTo( &object->getValue(), doc, Node_value, true );
		contNode.appendChild(Node_value);

		QDomElement Node_perm = doc.createElement("Permission");
		EncoderXML_template__Permission().serializeTo( &object->getPermission(), doc, Node_perm, true );
		contNode.appendChild(Node_perm);
	 }
	
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Property::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Property* object = dynamic_cast<Property*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement contNode_key = contNode.namedItem("key").toElement();
	if ( !contNode_key.isNull() )
		object->setKey( string( contNode_key.text().toLatin1().data() ) );
	else
		object->setKey( string( contNode.attribute("key").toLatin1().data() ) );

	QDomElement valueNode = contNode.namedItem("value").toElement();
	if ( !valueNode.isNull() ) {
		ret += EncoderXML_template__Variant().deserializeFrom( &object->getValue(), valueNode );
	 }
	else if ( contNode.attribute("value").size() > 0 )
		object->getValue().fromString( string( contNode.attribute("value").toLatin1().data() ) );
	else {
		if ( contNode.attribute("type").size() > 0 ) {
			//object->getValue().setType(Data::getDataTypeFromString(contNode.attribute("type").toLatin1().data(),true));
			object->getValue().fromString(contNode.text().toLatin1().data());
		}
		else
			object->getValue().fromString(contNode.text().toLatin1().data());
	}

	QDomElement permNode = contNode.namedItem("Permission").toElement();
	if ( !permNode.isNull() ) {
		ret += EncoderXML_template__Permission().deserializeFrom( &object->getPermission(), permNode );
	 }
	else if ( contNode.attribute("permission").size() > 0 )
		object->getPermission().fromString( string( contNode.attribute("permission").toLatin1().data() ) );

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__PropertiesProvider::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const PropertiesProvider* object = dynamic_cast<const PropertiesProvider*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	WRESULT ret = WRET_OK;
	WRESULT ret_t = WRET_OK;
	EncoderXML_template__Property encoder;

	PropertiesProvider::ConstIterator it;
	object->transactionBeginRead();
	const PropertiesProvider::ConstIterator it_end = object->getMap().end();
	for( it=object->getMap().begin(); it!=it_end; ++it ) {
		if ( it->second == NULL ) continue;
		if ( it->second->data == NULL ) continue;
		QDomElement dataNode = doc.createElement("property");
		ret_t = encoder.serializeTo( it->second->data, doc, dataNode, compact );
		if ( WSUCCEEDED(ret_t) )
			contNode.appendChild(dataNode);
		ret += ret_t;
	 }
	object->transactionEnd();

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__PropertiesProvider::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	PropertiesProvider* object = dynamic_cast<PropertiesProvider*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	WRESULT ret = WRET_OK;
	Property prop_element;
	string tagname;
	EncoderXML_template__Property encoder;

	QDomNodeList nodesList = contNode.childNodes();
	for( unsigned int j=0; j<nodesList.length(); ++j ) {
		QDomElement childNode = nodesList.item(j).toElement();
//		tagname = string( child.tagName().toLatin1().data() );
		encoder.deserializeFrom( &prop_element, childNode );
		object->set(prop_element);
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ObjectTypeInfo::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const ObjectTypeInfo* object = dynamic_cast<const ObjectTypeInfo*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( compact ) {
		contNode.setAttribute("name", QString(object->name.c_str()) );
		contNode.setAttribute("parent", QString(object->parent.c_str()) );
		contNode.setAttribute("version", QString::number(object->version) );
		contNode.setAttribute("allocable", QString::number((int)object->allocable) );
	 }
	else {
		QDomElement Node_name = doc.createElement("name");
		Node_name.appendChild( doc.createTextNode( QString(object->name.c_str()) ) );
		contNode.appendChild(Node_name);
		QDomElement Node_parent = doc.createElement("parent");
		Node_parent.appendChild( doc.createTextNode( QString(object->parent.c_str()) ) );
		contNode.appendChild(Node_parent);
		QDomElement Node_version = doc.createElement("version");
		Node_version.appendChild( doc.createTextNode( QString::number(object->version) ) );
		contNode.appendChild(Node_version);
		QDomElement Node_allocable = doc.createElement("allocable");
		Node_allocable.appendChild( doc.createTextNode( QString::number((int)object->allocable) ) );
		contNode.appendChild(Node_allocable);
	 }
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__ObjectTypeInfo::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	ObjectTypeInfo* object = dynamic_cast<ObjectTypeInfo*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement contNode_name = contNode.namedItem("name").toElement();
	if ( !contNode_name.isNull() )
		object->name = string( contNode_name.text().toLatin1().data() );
	else if ( contNode.hasAttribute("name") )
		object->name = string( contNode.attribute("name").toLatin1().data() );

	QDomElement contNode_parent = contNode.namedItem("parent").toElement();
	if ( !contNode_parent.isNull() )
		object->parent = string( contNode_parent.text().toLatin1().data() );
	else if ( contNode.hasAttribute("parent") )
		object->parent = string( contNode.attribute("parent").toLatin1().data() );

	QDomElement contNode_version = contNode.namedItem("version").toElement();
	if ( !contNode_version.isNull() )
		object->version = contNode_version.text().toDouble();
	else if ( contNode.hasAttribute("version") )
		object->version = contNode.attribute("version").toDouble();

	QDomElement contNode_allocable = contNode.namedItem("allocable").toElement();
	if ( !contNode_allocable.isNull() )
		object->allocable = (bool)contNode_allocable.text().toInt();
	else if ( contNode.hasAttribute("allocable") )
		object->allocable = (bool)contNode.attribute("allocable").toInt();

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


WRESULT EncoderXML_template__Object::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Object* object = dynamic_cast<const Object*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( compact ) {
		contNode.setAttribute("name", QString(object->getName().c_str()) );
		contNode.setAttribute("type", QString(object->getClassName()) );
		if ( !object->getURI().isEmpty() )
			contNode.setAttribute("uri", QString(object->getURI().toString().c_str()) );
		if ( !object->getPermission().isEmpty() )
			contNode.setAttribute("permission", QString(object->getPermission().toString().c_str()) );
	 }
	else {
		QDomElement headNode_name = doc.createElement("name");
		headNode_name.appendChild( doc.createTextNode( QString(object->getName().c_str()) ) );
		contNode.appendChild(headNode_name);

		QDomElement Node_type = doc.createElement("type");
		Node_type.appendChild( doc.createTextNode( QString(object->getClassName()) ) );
		contNode.appendChild(Node_type);

		if ( !object->getURI().isEmpty() ) {
			QDomElement Node_uri = doc.createElement("uri");
			Node_uri.appendChild( doc.createTextNode( QString(object->getURI().toString().c_str()) ) );
			contNode.appendChild(Node_uri);
		 }
		if ( !object->getPermission().isEmpty() ) {
			QDomElement Node_perm = doc.createElement("Permission");
			EncoderXML_template__Permission().serializeTo( &object->getPermission(), doc, Node_perm, true );
			contNode.appendChild(Node_perm);
		 }
	 }
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Object::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Object* object = dynamic_cast<Object*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement contNode_name = contNode.namedItem("name").toElement();
	if ( !contNode_name.isNull() )
		object->setName( string( contNode_name.text().toLatin1().data() ) );
	else if ( contNode.hasAttribute("name") )
		object->setName( string( contNode.attribute("name").toLatin1().data() ) );

	QDomElement contNode_uri = contNode.namedItem("uri").toElement();
	if ( !contNode_uri.isNull() )
		object->getURI().fromString( string( contNode_uri.text().toLatin1().data() ) );
	else if ( contNode.hasAttribute("uri") )
		object->getURI().fromString( string( contNode.attribute("uri").toLatin1().data() ) );

	// type check
	std::string type;
	QDomElement contNode_type = contNode.namedItem("type").toElement();
	if ( !contNode_type.isNull() )
		type = string( contNode_type.text().toLatin1().data() );
	else if ( contNode.hasAttribute("type") )
		type = string( contNode.attribute("type").toLatin1().data() );
	if ( !object->isClass(type.c_str()) ) {
		// error
	 }

	Permission perm;
	QDomElement permNode = contNode.namedItem("Permission").toElement();
	if ( !permNode.isNull() ) {
		ret += EncoderXML_template__Permission().deserializeFrom( &perm, permNode );
	 }
	else if ( contNode.hasAttribute("Permission") )
		perm.fromString( string( contNode.attribute("permission").toLatin1().data() ) );
	object->setPermission(perm);

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Message::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Message* object = dynamic_cast<const Message*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( object->getID()!= 0 ) {
	 	QDomElement headNode_id = doc.createElement("id");
		headNode_id.appendChild( doc.createTextNode( QString::number(object->getID()) ) );
		contNode.appendChild(headNode_id);
	}
	if ( object->getReferenceID() != 0 ) {
	 	QDomElement headNode_rid = doc.createElement("refid");
		headNode_rid.appendChild( doc.createTextNode( QString::number(object->getReferenceID()) ) );
		contNode.appendChild(headNode_rid);
	}
	if ( object->getTimestamp() != 0 ) {
		QDomElement headNode_ts = doc.createElement("timestamp");
		headNode_ts.appendChild( doc.createTextNode( QString::number(object->getTimestamp()) ) );
		contNode.appendChild(headNode_ts);
	}

	QDomElement headNode_source = doc.createElement("source");
	headNode_source.appendChild( doc.createTextNode( QString(object->getSource().toString().c_str()) ) );
	headNode_source.setAttribute("bus", QString(object->getSourceBus().c_str()) );
	if ( !object->getSourceUUID().empty() )
		headNode_source.setAttribute("uuid", QString(object->getSourceUUID().c_str()) );
	contNode.appendChild(headNode_source);

	QDomElement headNode_dest = doc.createElement("destination");
	headNode_dest.appendChild( doc.createTextNode( QString(object->getDestination().toString().c_str()) ) );
	headNode_dest.setAttribute("bus", QString(object->getDestinationBus().c_str()) );
	if ( !object->getDestinationUUID().empty() )
		headNode_source.setAttribute("uuid", QString(object->getDestinationUUID().c_str()) );
	contNode.appendChild(headNode_dest);

	WRESULT ret = WRET_OK;
	const MessageContent* content = object->getContent();
	if ( content != NULL ) {
		QDomElement node_content = doc.createElement( "content" );
		node_content.setAttribute("classname", content->getClassName() );
		ret = EncoderXML::serializeTo(content, doc, node_content, compact);
		contNode.appendChild(node_content);
	 }

	const SecurityToken* secObj = object->getSecurityToken();
	if ( secObj != NULL ) {
		QDomElement node_security = doc.createElement("security");
		ret += EncoderXML::serializeTo(secObj, doc, node_security, compact);
		contNode.appendChild(node_security);
	 }
	
	const MessageNetworkForwarding* forwObj = object->getNetworkForwarders();
	if ( forwObj != NULL ) {
		QDomElement node_forwarding = doc.createElement("forwarding");
		ret += EncoderXML::serializeTo(forwObj, doc, node_forwarding, compact);
		contNode.appendChild(node_forwarding);
	 }

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Message::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Message* object = dynamic_cast<Message*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

//	this->id = headNode.namedItem("id").toElement().text().toInt();
//	this->ref_id = headNode.namedItem("refid").toElement().text().toInt();

	long id = contNode.namedItem("id").toElement().text().toInt();
	long ref_id = contNode.namedItem("refid").toElement().text().toInt();
	long ts = contNode.namedItem("timestamp").toElement().text().toInt();
	message_assign(object, id, ref_id, ts );
	
	QDomElement sourceNode = contNode.namedItem("source").toElement();
	if ( !sourceNode.isNull() )	{
		if ( sourceNode.text().length() > 0 )
			object->getSource().fromString( string( sourceNode.text().toLatin1().data() ) );
		if ( sourceNode.hasAttribute("bus") )
			object->setSourceBus( string( sourceNode.attribute("bus").toLatin1().data() ) );
		if ( sourceNode.hasAttribute("uuid") )
			object->setSourceUUID( string( sourceNode.attribute("uuid").toLatin1().data() ) );
	}

	QDomElement targetNode = contNode.namedItem("destination").toElement();
	if ( !targetNode.isNull() )	{
		if(targetNode.text().length() > 0 )
			object->getDestination().fromString( string( targetNode.text().toLatin1().data() ) );
		if ( targetNode.hasAttribute("bus") )
			object->setDestinationBus( string( targetNode.attribute("bus").toLatin1().data() ) );
		if ( targetNode.hasAttribute("uuid") )
			object->setDestinationUUID( string( targetNode.attribute("uuid").toLatin1().data() ) );
	}

	WRESULT ret = WRET_OK;

	QDomElement contentNode = contNode.namedItem("content").toElement();
	if ( contentNode.isNull() ) {
		object->setContent(NULL);
	 }
	else {
		string content_type( contentNode.attribute("classname").toLatin1().data() );
		EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(content_type);
		if ( obj_ser != NULL ) {
			ISerializable* content_data = obj_ser->allocObject();
			ret = obj_ser->deserializeFrom(content_data, contentNode);
			MessageContent* msgcontent = dynamic_cast<MessageContent*>(content_data);
			object->setContent(msgcontent);
		 }
	 }

	QDomElement securityNode = contNode.namedItem("security").toElement();
	if ( !securityNode.isNull() ) {
		SecurityToken* security = new SecurityToken();
		EncoderXML_template__SecurityToken sec_enc;
		ret += sec_enc.deserializeFrom( security, securityNode );
		object->setSecurityToken( security );
	}

	QDomElement forwardingNode = contNode.namedItem("forwarding").toElement();
	if ( !forwardingNode.isNull() ) {
		MessageNetworkForwarding* forwarding = new MessageNetworkForwarding();
		EncoderXML_template__MessageNetworkForwarding forw_enc;
		ret += forw_enc.deserializeFrom( forwarding, forwardingNode );
		object->setNetworkForwarders( forwarding );
	}

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


WRESULT EncoderXML_template__MessageFilter::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const wosh::MessageFilter* object = dynamic_cast<const wosh::MessageFilter*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	ret = EncoderXML_template__Message().serializeTo( object_s, doc, contNode, compact );

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__MessageFilter::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	wosh::MessageFilter* object = dynamic_cast<wosh::MessageFilter*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	ret = EncoderXML_template__Message().deserializeFrom( object_s, contNode );

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__SecurityToken::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const SecurityToken* object = dynamic_cast<const SecurityToken*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( object->getUser() != "" ) {
		QDomElement headNode_dest = doc.createElement("user");
		headNode_dest.appendChild( doc.createTextNode( QString(object->getUser().c_str()) ) );
		contNode.appendChild(headNode_dest);
	 }
	
	(void)compact;

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__SecurityToken::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	SecurityToken* object = dynamic_cast<SecurityToken*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement userNode = contNode.namedItem("user").toElement();
	if ( userNode.isNull() )
		object->user = string( contNode.attribute("user").toLatin1().data() );
	else
		object->user = string( userNode.text().toLatin1().data() );

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__MessageNetworkForwarding::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	(void)compact;
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const MessageNetworkForwarding* object = dynamic_cast<const MessageNetworkForwarding*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	std::vector<MessageNetworkForwarder>::const_iterator it;
	for ( it=object->getHosts().begin(); it!=object->getHosts().end(); ++it ) {
		QDomElement forwNode = doc.createElement("forwarder");
		forwNode.appendChild( doc.createTextNode( QString((*it).name.c_str()) ) );
		forwNode.setAttribute("timestamp", QString::number((*it).timestamp) );
		contNode.appendChild(forwNode);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__MessageNetworkForwarding::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	MessageNetworkForwarding* object = dynamic_cast<MessageNetworkForwarding*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomNodeList nodesList = contNode.childNodes();
	for( unsigned int j=0; j<nodesList.length(); ++j ) {
		QDomElement childNode = nodesList.item(j).toElement();
		if ( childNode.text().isEmpty() ) continue;
		MessageNetworkForwarder mnf;
		mnf.name = string( childNode.text().toLatin1().data() );
		mnf.timestamp = childNode.attribute("timestamp").toLong();
		object->getHosts().push_back(mnf);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Request::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Request* object = dynamic_cast<const Request*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( compact ) {
		contNode.setAttribute("method", QString(object->getMethod().c_str()) );
		if ( object->doOmitResponse() )
			contNode.setAttribute("omitResponse", "1" );
	 }
	else {
		QDomElement methodNode = doc.createElement("method");
		methodNode.appendChild( doc.createTextNode( QString(object->getMethod().c_str()) ) );
		contNode.appendChild(methodNode);
		if ( object->doOmitResponse() )
			methodNode.setAttribute("omitResponse", "1" );
		//QDomElement omitNode = doc.createElement("omitResponse");
		//omitNode.appendChild( doc.createTextNode( QString::number((short)object->doOmitResponse()) ) );
		//contNode.appendChild(omitNode);
	 }

	if ( object->hasData() ) {
		const ISerializable* content = object->getData();
		QDomElement contentNode = doc.createElement("content");
		contentNode.setAttribute("classname", QString(content->getClassName()) );
		EncoderXML::serializeTo(content, doc, contentNode, compact );
		contNode.appendChild(contentNode);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// win CE ERROR
WRESULT EncoderXML_template__Request::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Request* object = dynamic_cast<Request*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement methodNode = contNode.namedItem("method").toElement();
	if ( methodNode.isNull() )
		object->setMethod( string( contNode.attribute("method").toLatin1().data() ) );
	else
		object->setMethod( string( methodNode.text().toLatin1().data() ) );

	QDomElement omitNode = contNode.namedItem("omitResponse").toElement();
	QString omitStr = "";
	if ( omitNode.isNull() )
		omitStr = contNode.attribute("omitResponse");
	else
		omitStr = omitNode.text();
	if ( omitStr == "true" )
		object->setOmitResponse(true);
	else if ( omitStr == "false" )
		object->setOmitResponse(false);
	else
		object->setOmitResponse( (bool)omitStr.toInt() );


	QDomElement contentNode = contNode.namedItem("content").toElement();
	if ( contentNode.isNull() ) {
		
	 }
	else {
		string tagname( contentNode.attribute("classname").toLatin1().data() );
		EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(tagname);
		if ( obj_ser == NULL ) {
			return WRET_ERR_INTERNAL;
		 }
		ISerializable* content_data = obj_ser->allocObject();
		WRESULT ret = obj_ser->deserializeFrom(content_data, contentNode);
		(void)ret;
		object->setData(content_data);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Response::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Response* object = dynamic_cast<const Response*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( compact ) {
		contNode.setAttribute("method", QString(object->getMethod().c_str()) );
		contNode.setAttribute("returnValue", QString::number(object->getReturnValue()) );
	 }
	else {
		QDomElement methodNode = doc.createElement("method");
		methodNode.appendChild( doc.createTextNode( QString(object->getMethod().c_str()) ) );
		contNode.appendChild(methodNode);
		QDomElement returnNode = doc.createElement("returnValue");
		returnNode.appendChild( doc.createTextNode( QString::number(object->getReturnValue()) ) );
		contNode.appendChild(returnNode);
	 }

	if ( object->hasData() ) {
		const ISerializable* content = object->getData();
		QDomElement contentNode = doc.createElement("content");
		contentNode.setAttribute("classname", QString(content->getClassName()) );
		EncoderXML::serializeTo(content, doc, contentNode, compact );
		contNode.appendChild(contentNode);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Response::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Response* object = dynamic_cast<Response*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement methodNode = contNode.namedItem("method").toElement();
	if ( methodNode.isNull() )
		object->setMethod( string( contNode.attribute("method").toLatin1().data() ) );
	else
		object->setMethod( string( methodNode.text().toLatin1().data() ) );

	QDomElement returnNode = contNode.namedItem("returnValue").toElement();
	if ( returnNode.isNull() )
		object->setReturnValue( contNode.attribute("returnValue").toInt() );
	else
		object->setReturnValue( returnNode.text().toInt() );

	QDomElement contentNode = contNode.namedItem("content").toElement();
	if ( contentNode.isNull() ) {
		
	 }
	else {
		string tagname( contentNode.attribute("classname").toLatin1().data() );
		EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(tagname);
		if ( obj_ser == NULL ) {
			return WRET_ERR_INTERNAL;
		 }
		ISerializable* content_data = obj_ser->allocObject();
		WRESULT ret = obj_ser->deserializeFrom(content_data, contentNode);
		(void)ret;
		object->setData(content_data);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Fact::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Fact* object = dynamic_cast<const Fact*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	if ( compact ) {
		contNode.setAttribute("event", QString(object->getEvent().c_str()) );
	 }
	else {
		QDomElement eventNode = doc.createElement("event");
		eventNode.appendChild( doc.createTextNode( QString(object->getEvent().c_str()) ) );
		contNode.appendChild(eventNode);
	 }

	if ( object->hasData() ) {
		const ISerializable* content = object->getData();
		QDomElement contentNode = doc.createElement("content");
		contentNode.setAttribute("classname", QString(content->getClassName()) );
		EncoderXML::serializeTo(content, doc, contentNode, compact );
		contNode.appendChild(contentNode);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Fact::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Fact* object = dynamic_cast<Fact*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement eventNode = contNode.namedItem("event").toElement();
	if ( eventNode.isNull() )
		object->setEvent( string( contNode.attribute("event").toLatin1().data() ) );
	else
		object->setEvent( string( eventNode.text().toLatin1().data() ) );

	QDomElement contentNode = contNode.namedItem("content").toElement();
	if ( contentNode.isNull() ) {
		
	 }
	else {
		string tagname( contentNode.attribute("classname").toLatin1().data() );
		EncoderXML_base* obj_ser = EncoderXML::findEncoderFor(tagname);
		if ( obj_ser == NULL ) {
			return WRET_ERR_INTERNAL;
		 }
		ISerializable* content_data = obj_ser->allocObject();
		WRESULT ret = obj_ser->deserializeFrom(content_data, contentNode);
		(void)ret;
		object->setData(content_data);
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Notification::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const Notification* object = dynamic_cast<const Notification*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	contNode.setAttribute("id", QString::number(object->getID()) );
	contNode.setAttribute("flow", QString::number(object->getFlowID()) );

	if ( compact ) {
		contNode.setAttribute("timestamp", QString::number(object->getTimeStamp()) );
		contNode.setAttribute("priority", QString::number((int)object->getPriority()) );
		contNode.setAttribute("protocol", QString::number((int)object->getProtocol()) );
	}
	else {
		QDomElement ts_node = doc.createElement("timestamp");
		ts_node.appendChild( doc.createTextNode( QString::number(object->getTimeStamp()) ) );
		contNode.appendChild(ts_node);
		QDomElement protocol_node = doc.createElement("protocol");
		protocol_node.appendChild( doc.createTextNode( QString::number((int)object->getProtocol()) ) );
		contNode.appendChild(protocol_node);
		QDomElement priority_node = doc.createElement("priority");
		priority_node.appendChild( doc.createTextNode( QString::number((int)object->getPriority()) ) );
		contNode.appendChild(priority_node);
	}

	QDomElement sender_node = doc.createElement("sender");
	sender_node.setAttribute("id", QString(object->getSender_ID().c_str()) );
	sender_node.setAttribute("user", QString(object->getSender_User().c_str()) );
	contNode.appendChild(sender_node);

	QDomElement recipent_node = doc.createElement("recipent");
	recipent_node.setAttribute("id", QString(object->getRecipent_ID().c_str()) );
	recipent_node.setAttribute("user", QString(object->getRecipent_User().c_str()) );
	recipent_node.setAttribute("group", QString(object->getRecipent_Group().c_str()) );
	contNode.appendChild(recipent_node);

	if ( object->getReadTimeStamp() != 0 ) {
		QDomElement rtsNode = doc.createElement("read_timestamp");
		rtsNode.appendChild( doc.createTextNode( QString::number(object->getReadTimeStamp()) ) );
		contNode.appendChild(rtsNode);
	 }
	if ( object->getSentTimeStamp() != 0 ) {
		QDomElement stsNode = doc.createElement("sent_timestamp");
		stsNode.appendChild( doc.createTextNode( QString::number(object->getSentTimeStamp()) ) );
		contNode.appendChild(stsNode);
	 }

	QDomElement langNode = doc.createElement("language");
	langNode.appendChild( doc.createTextNode( QString(object->getLanguage().c_str()) ) );
	contNode.appendChild(langNode);

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__Notification::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	Notification* object = dynamic_cast<Notification*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	object->uid = contNode.attribute("id").toLong();
	object->flow_uid = contNode.attribute("flow").toLong();

	QDomElement tsNode = contNode.namedItem("timestamp").toElement();
	if ( tsNode.isNull()  )
		object->setTimeStamp( contNode.attribute("timestamp").toLong() );
	else
		object->setTimeStamp( tsNode.text().toLong() );

	QDomElement protoNode = contNode.namedItem("protocol").toElement();
	if ( protoNode.isNull()  )
		object->setProtocol( (Notification::PROTOCOL)contNode.attribute("protocol").toInt() );
	else
		object->setProtocol( (Notification::PROTOCOL)protoNode.text().toInt() );

	QDomElement priorityNode = contNode.namedItem("priority").toElement();
	if ( priorityNode.isNull()  )
		object->setPriority( (Notification::PRIORITY)contNode.attribute("priority").toInt() );
	else
		object->setPriority( (Notification::PRIORITY)priorityNode.text().toInt() );

	QDomElement sender_node = contNode.namedItem("sender").toElement();
	if ( !sender_node.isNull() ) {
		object->setSender_ID( string( sender_node.attribute("id").toLatin1().data() ) );
		object->setSender_User( string( sender_node.attribute("user").toLatin1().data() ) );
	 }

	QDomElement recipent_node = contNode.namedItem("recipent").toElement();
	if ( !recipent_node.isNull() ) {
		object->setRecipent_ID( string( recipent_node.attribute("id").toLatin1().data() ) );
		object->setRecipent_User( string( recipent_node.attribute("user").toLatin1().data() ) );
		object->setRecipent_Group( string( recipent_node.attribute("group").toLatin1().data() ) );
	 }

	QDomElement rtsNode = contNode.namedItem("read_timestamp").toElement();
	if ( !rtsNode.isNull() ) {
		object->setRead(true, rtsNode.text().toLong() );
	 }
	QDomElement stsNode = contNode.namedItem("sent_timestamp").toElement();
	if ( !stsNode.isNull() ) {
		object->setSent(true, stsNode.text().toLong() );
	 }

	QDomElement langNode = contNode.namedItem("language").toElement();
	if ( langNode.isNull()  )
		object->setLanguage( string( contNode.attribute("language").toLatin1().data() ) );
	else
		object->setLanguage( string( langNode.text().toLatin1().data() ) );


	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__SystemError::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const SystemError* object = dynamic_cast<const SystemError*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement eidNode = doc.createElement("error-id");
	eidNode.appendChild( doc.createTextNode( QString::number(object->getID()) ) );
	contNode.appendChild(eidNode);

	QDomElement ecNode = doc.createElement("error-code");
	ecNode.appendChild( doc.createTextNode( QString::number(object->getErrorCode()) ) );
	contNode.appendChild(ecNode);

	if ( !object->getMethod().empty() ) {
		QDomElement methodNode = doc.createElement("method");
		methodNode.appendChild( doc.createTextNode( QString(object->getMethod().c_str()) ) );
		contNode.appendChild(methodNode);
	 }

	if ( !object->getSource().isEmpty() ) {
		QDomElement uriNode = doc.createElement("source-uri");
		uriNode.appendChild( doc.createTextNode( QString(object->getSource().toString().c_str()) ) );
		contNode.appendChild(uriNode);
	 }

	QDomElement priorityNode = doc.createElement("priority");
	priorityNode.appendChild( doc.createTextNode( QString::number((int)object->getPriority()) ) );
	contNode.appendChild(priorityNode);

	if ( !object->getDescription().empty() ) {
		QDomElement descrNode = doc.createElement("description");
		descrNode.appendChild( doc.createTextNode( QString(object->getDescription().c_str()) ) );
		contNode.appendChild(descrNode);
	 }

	(void)compact;
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__SystemError::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	SystemError* object = dynamic_cast<SystemError*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement eidNode = contNode.namedItem("error-id").toElement();
	if ( eidNode.isNull()  )
		object->uid = contNode.attribute("error-id").toLong();
	else
		object->uid = eidNode.text().toLong();

	QDomElement ecNode = contNode.namedItem("error-code").toElement();
	if ( ecNode.isNull()  )
		object->setErrorCode( contNode.attribute("error-code").toLong() );
	else
		object->setErrorCode( ecNode.text().toLong() );

	QDomElement methodNode = contNode.namedItem("method").toElement();
	if ( methodNode.isNull()  )
		object->setMethod( string( contNode.attribute("method").toLatin1().data() ) );
	else
		object->setMethod( string( methodNode.text().toLatin1().data() ) );

	QDomElement uriNode = contNode.namedItem("source-uri").toElement();
	if ( uriNode.isNull()  )
		object->getSource().fromString( string( contNode.attribute("source-uri").toLatin1().data() ) );
	else
		object->getSource().fromString( string( uriNode.text().toLatin1().data() ) );

	QDomElement priorityNode = contNode.namedItem("priority").toElement();
	if ( priorityNode.isNull()  )
		object->setPriority( (SystemError::PRIORITY) contNode.attribute("priority").toLong() );
	else
		object->setPriority( (SystemError::PRIORITY) priorityNode.text().toLong() );

	QDomElement descriptionNode = contNode.namedItem("description").toElement();
	if ( descriptionNode.isNull()  )
		object->setDescription( string( contNode.attribute("description").toLatin1().data() ) );
	else
		object->setDescription( string( descriptionNode.text().toLatin1().data() ) );

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__User::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const User* object = dynamic_cast<const User*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	if ( compact ) {
		ret += EncoderXML_template__Object().serializeTo( object, doc, contNode, true );

	 }
	else {
		QDomElement objectNode = doc.createElement("object");
		contNode.appendChild(objectNode);
		ret += EncoderXML_template__Object().serializeTo( object, doc, objectNode, false );

	 }

	if ( compact ) {
//		contNode.setAttribute("id", QString::number(object->id) );
		//contNode.setAttribute("name", QString(object->getName().c_str()) );
	 }
	else {
	 }

	QDomElement passwordNode = doc.createElement("password");
	passwordNode.appendChild( doc.createTextNode( QString(object->pwd.c_str()) ) );
	passwordNode.setAttribute("type", QString(object->pwd_proto.c_str()) );
	contNode.appendChild(passwordNode);

	QDomElement groups_node = doc.createElement("groups");
	std::vector<std::string>::const_iterator itp;
	for ( itp=object->groups.begin(); itp!=object->groups.end(); ++itp ) {
		QDomElement group_node = doc.createElement("groups");
		group_node.appendChild( doc.createTextNode( QString(itp->c_str()) ));
		groups_node.appendChild(group_node);
	 }
	contNode.appendChild(groups_node);

	QDomElement node_properties= doc.createElement("properties");
	ret += EncoderXML_template__PropertiesProvider().serializeTo( &object->Properties, doc, node_properties, compact );
	contNode.appendChild(node_properties);

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__User::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	User* object = dynamic_cast<User*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;

	QDomElement objectNode = contNode.namedItem("object").toElement();
	if ( !objectNode.isNull() )
		ret += EncoderXML_template__Object().deserializeFrom( object, objectNode );
	else
		ret += EncoderXML_template__Object().deserializeFrom( object, contNode );

	QDomElement contNode_id = contNode.namedItem("id").toElement();
	if ( contNode_id.isNull() )
		object->id = contNode.attribute("id").toLong();
	else
		object->id = contNode_id.text().toLong();

	object->getProperties().set( _KEY_id, object->id );

	QDomElement contNode_pwd = contNode.namedItem("password").toElement();
	if ( contNode_pwd.isNull() )
		object->pwd = string( contNode.attribute("password").toLatin1().data() );
	else {
		object->pwd = string( contNode_pwd.text().toLatin1().data() );
		object->pwd_proto = string( contNode_pwd.attribute("type").toLatin1().data() );
	 }

	QDomElement groups_node = contNode.namedItem("groups").toElement();
	QDomNodeList groupsList = groups_node.childNodes();
	for( unsigned int j=0; j<groupsList.length(); ++j ) {
		QDomElement childNode = groupsList.item(j).toElement();
		object->groups.push_back( string(childNode.text().toLatin1().data()) );
	 }

	QDomElement propsNode = contNode.namedItem("properties").toElement();
	if ( !propsNode.isNull() ) {
		ret += EncoderXML_template__PropertiesProvider().deserializeFrom( &object->getProperties(), propsNode );
	 }

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__WoshHost::serializeTo( const ISerializable* object_s, QDomDocument& doc, QDomElement& contNode, bool compact )
 {
	if ( object_s == NULL ) return WRET_ERR_PARAM;
	const WoshHost* object = dynamic_cast<const WoshHost*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	(void)compact;
	contNode.setAttribute("name", QString(object->getName().c_str()) );
	contNode.setAttribute("protocol", QString::number(object->getDiscoveryProtocolVersion()) );
	contNode.setAttribute("last-seen", QString::number(object->getSeen()) );

	QDomElement discovery_node = doc.createElement("discovery");
	discovery_node.setAttribute("source", QString(object->getDiscoverySource().c_str()) );
	discovery_node.setAttribute("bind-address", QString(object->getDiscoveryBindAddress().c_str()) );
	discovery_node.setAttribute("notify-frequency", QString::number(object->getNotifyFrequency()) );
	contNode.appendChild(discovery_node);

	QDomElement kernel_node = doc.createElement("kernel");
	kernel_node.setAttribute("state", QString::number(object->getKernelState()) );
	contNode.appendChild(kernel_node);


	QDomElement protocols_node = doc.createElement("protocols");
	std::vector<std::string>::const_iterator itp;
	for ( itp=object->getProtocols().begin(); itp!=object->getProtocols().end(); ++itp ) {
		QDomElement protocol_node = doc.createElement("protocol");
		protocol_node.appendChild( doc.createTextNode( QString(itp->c_str()) ));
		protocols_node.appendChild(protocol_node);
	 }
	contNode.appendChild(protocols_node);

	QDomElement connections_node = doc.createElement("connections");
	std::map<std::string,long>::const_iterator it;
	for ( it=object->getConnections().begin(); it!=object->getConnections().end(); ++it ) {
		QDomElement conn_node = doc.createElement("connection");
		conn_node.appendChild( doc.createTextNode( QString(it->first.c_str()) ));
		conn_node.setAttribute("channel", QString::number(it->second) );
		connections_node.appendChild(conn_node);	
	 }
	contNode.appendChild(connections_node);

	QDomElement neighbours_node = doc.createElement("neighbours");
	std::map<std::string,long>::const_iterator itn;
	for ( itn=object->getNeighbours().begin(); itn!=object->getNeighbours().end(); ++itn ) {
		QDomElement conn_node = doc.createElement("neighbour");
		conn_node.appendChild( doc.createTextNode( QString(itn->first.c_str()) ));
		conn_node.setAttribute("timestamp", QString::number(itn->second) );
		connections_node.appendChild(conn_node);	
	 }
	contNode.appendChild(neighbours_node);


	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderXML_template__WoshHost::deserializeFrom( ISerializable* object_s, const QDomElement& contNode )
 {
 	if ( object_s == NULL ) return WRET_ERR_PARAM;
	WoshHost* object = dynamic_cast<WoshHost*>(object_s);
	if ( object == NULL ) return WRET_ERR_PARAM;

	QDomElement contNode_name = contNode.namedItem("name").toElement();
	if ( contNode_name.isNull() )
		object->setName( string( contNode.attribute("name").toLatin1().data() ) );
	else
		object->setName( string( contNode_name.text().toLatin1().data() ) );

	QDomElement contNode_ls = contNode.namedItem("last-seen").toElement();
	if ( contNode_ls.isNull() )
		object->setSeen( contNode.attribute("last-seen").toLong() );
	else
		object->setSeen( contNode_ls.text().toLong() );

	QDomElement contNode_ds_node = contNode.namedItem("discovery").toElement();
	if ( !contNode_ds_node.isNull() ) {
		QDomElement contNode_ds = contNode_ds_node.namedItem("source").toElement();
		if ( contNode_ds.isNull() )
			object->setDiscoverSource( string( contNode_ds_node.attribute("source").toLatin1().data() ) );
		else
			object->setDiscoverSource( string( contNode_ds.text().toLatin1().data() ) );

		QDomElement contNode_dba = contNode_ds_node.namedItem("bind-address").toElement();
		if ( contNode_dba.isNull() )
			object->setDiscoverSource( string( contNode_ds_node.attribute("bind-address").toLatin1().data() ) );
		else
			object->setDiscoverSource( string( contNode_dba.text().toLatin1().data() ) );

		QDomElement contNode_nf = contNode_ds_node.namedItem("notify-frequency").toElement();
		if ( contNode_nf.isNull() )
			object->setNotifyFrequency( contNode_ds_node.attribute("notify-frequency").toLong() );
		else
			object->setNotifyFrequency( contNode_nf.text().toLong() );
	 }

	QDomElement contNode_k_node = contNode.namedItem("kernel").toElement();
	if ( !contNode_k_node.isNull() ) {
		QDomElement contNode_ks = contNode_k_node.namedItem("state").toElement();
		if ( contNode_ks.isNull() )
			object->setKernelState( contNode_ks.attribute("state").toLong() );
		else
			object->setKernelState( contNode_ks.text().toLong() );
	 }


	QDomElement protocols_node = contNode.namedItem("protocols").toElement();
	QDomNodeList protocolsList = protocols_node.childNodes();
	for( unsigned int j=0; j<protocolsList.length(); ++j ) {
		QDomElement childNode = protocolsList.item(j).toElement();
		object->getProtocols().push_back( string(childNode.text().toLatin1().data()) );
	 }

	QDomElement conns_node = contNode.namedItem("connections").toElement();
	QDomNodeList connsList = conns_node.childNodes();
	for( unsigned int j=0; j<connsList.length(); ++j ) {
		QDomElement childNode = connsList.item(j).toElement();
		object->getConnections()[string(childNode.text().toLatin1().data())] = childNode.attribute("channel").toLong();
	 }

	QDomElement neighbours_node = contNode.namedItem("neighbours").toElement();
	QDomNodeList neighboursList = neighbours_node.childNodes();
	for( unsigned int j=0; j<neighboursList.length(); ++j ) {
		QDomElement childNode = neighboursList.item(j).toElement();
		object->getNeighbours()[string(childNode.text().toLatin1().data())] = childNode.attribute("timestamp").toLong();
	 }


	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }; // namespace database
}; // namespace wosh
